package com.example.web.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.admin.mapper.BlogMapper;
import com.example.admin.mapper.CategoryMapper;
import com.example.admin.service.BlogService;
import com.example.xo.pojo.Blog;
import com.example.xo.pojo.Category;
import com.example.xo.vo.BlogVO;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 王同学
 */
@Service
@Slf4j
public class BlogServiceimpl implements BlogService {
    @Autowired
    private BlogMapper blogMapper;

    @Autowired
    private CategoryMapper categoryMapper;

    @Override
    public boolean add(Blog blog) {
        //在新增的时候要判断标题是否重复，分类名不可重复（看需求文档）
        Blog blog1 = findBlogTitle(blog.getTitle());
        //判断一下返回上来的结果
        if (blog1 != null) {
            //如果不为空的话，说明标题已经存在，所以不能重复创建
            //再给一点小提示,提示重复了
            log.info("标题{}重复了", blog.getTitle());
            //那么就给他false
            return false;
        }
        //雪花算法加密 因为是string类型的所以尾巴要选择str
        String id = IdUtil.getSnowflakeNextIdStr();

        blog.setBlogId(id);

        //如果为空的话，就可以直接添加上去，说明没有重复的分类名
        int insert = blogMapper.insert(blog);
        //这边给的是int类型的，添加几条数据成功就会返回多少受影响
        //这边不做批量添加，所以就 返回1表示添加成功 不返回1就是失败
        log.info("添加了一个博客:{}", blog);
        return insert > 0;

    }

    @Override
    public boolean deleteById(String id) {

        //判断是否给软删除了
        Blog blog = findBlogId(id);
        //如果数据库中没有这个数据
        if (blog == null) {
            log.info("数据丢失:{}", blog);
            return false;
        }
        //给他加个删除时间
        blog.setDeleted(LocalDateTime.now());
        //选择这个id 把他删除掉
        LambdaQueryWrapper<Blog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Blog::getBlogId, id);
        //软删除，所以用的是修改，添加一下删除时间
        int del = blogMapper.update(blog, wrapper);
        //把他影响的行数反上去 >0
        return del > 0;
    }

    @Override
    public boolean update(Blog blog) {
        //加上条件 没有被软删除的，存在的，加上更新时间
        LambdaQueryWrapper<Blog> wrapper = new LambdaQueryWrapper<>();
        //存在的，没有被软删除的
        wrapper.eq(Blog::getBlogId, blog.getBlogId());
        wrapper.isNull(Blog::getDeleted);
        //加上更新时间
        blog.setUpdated(LocalDateTime.now());
        //再来个判断，判断一下标题是否重复 这是个方法(这个就是把我们传进来的 标题给他)
        //然后把结果返回到这边，因为方法里面的条件所以只会返回 重复或者null
        Blog blogTitle = findBlogTitle(blog.getTitle());
        // TODO: 2022/10/31 解决的一个问题
        // 然后把上面的结果拿下来判断 如果不为空（就是有标题重复）那么就会return出去
        //后面那个判断：调用数据库里面的博客id去对比 我们传进来的(根据标题查找的博客id)做对比
        //如果这两个id不一样的话，那么就给他return出去，如果都满足两个条件那么跳过判断往下执行
        if (blogTitle != null && !blog.getBlogId().equals(blogTitle.getBlogId())) {
            log.info("数据错误");
            return false;
        }
        //设置作者不可改，这边用了mybatis的特性
        blog.setAuthor(null);

        int up = blogMapper.update(blog, wrapper);
        return up > 0;
    }

    @Override
    public List<BlogVO> findAll() {
        List<BlogVO> vos = new ArrayList<>();
        //查询blog
        LambdaQueryWrapper<Blog> wrapper = new LambdaQueryWrapper<>();
        wrapper.isNull(Blog::getDeleted);
        wrapper.orderByDesc(Blog::getContent);
        List<Blog> res = blogMapper.selectList(wrapper);

        for (Blog r : res) {

            Category id = categoryMapper.selectById(r.getCategoryId());
            if (id == null) {
                continue;
            }
            BlogVO bvo = new BlogVO();
            bvo.setBlogId(r.getBlogId());
            bvo.setAuthor(r.getAuthor());
            bvo.setCategoryName(id.getCategoryName());
            bvo.setTitle(r.getTitle());
            bvo.setCreated(r.getCreated());
            vos.add(bvo);
        }

        return vos;
    }

    @Override
    public BlogVO findById(String id) {
        //查找blog
        LambdaQueryWrapper<Blog> wrapper = new LambdaQueryWrapper<>();
        wrapper.isNull(Blog::getDeleted);
        wrapper.eq(Blog::getBlogId, id);
        Blog blog = blogMapper.selectOne(wrapper);
        //判断是否传的是空的
        if (blog == null) {
            return null;
        }

        //这个可以封装起来

        return getBlogVO(blog);

    }

    @Override
    public BlogVO findByTitle(String title) {
        //查找blog
        LambdaQueryWrapper<Blog> wrapper = new LambdaQueryWrapper<>();
        wrapper.isNull(Blog::getDeleted);
        wrapper.eq(Blog::getTitle, title);
        Blog blog = blogMapper.selectOne(wrapper);
        //判断是否传的是空的
        if (blog == null) {
            return null;
        }

        //这个可以封装起来
        BlogVO bvo = getBlogVO(blog);

        return bvo;

    }

    @Override
    public Blog findBlogId(String id) {
        //查询blog的数据，查询的不能给软删除
        LambdaQueryWrapper<Blog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Blog::getBlogId, id); //查询blog库中的id是否一样
        wrapper.isNull(Blog::getDeleted);

        return blogMapper.selectOne(wrapper);
    }

    @Override
    public Blog findPoById(String id) {
        // TODO: 2022/11/4 这边这个方法有待商议
        LambdaQueryWrapper<Blog>wrapper=new LambdaQueryWrapper<>();
        wrapper.isNull(Blog::getDeleted);
        wrapper.eq(Blog::getBlogId,id);
        return blogMapper.selectOne(wrapper);
    }

    @NotNull
    private BlogVO getBlogVO(Blog blog) {
        //封装起来的方法
        BlogVO bvo = new BlogVO();
        Category res = categoryMapper.selectById(blog.getCategoryId());
        bvo.setBlogId(blog.getBlogId());
        bvo.setAuthor(blog.getAuthor());
        bvo.setCategoryName(res.getCategoryName());
        bvo.setTitle(blog.getTitle());
        bvo.setCreated(blog.getCreated());
        return bvo;
    }

    public Blog findBlogTitle(String title) {
        //查找blog
        LambdaQueryWrapper<Blog> wrapper = new LambdaQueryWrapper<>();
        wrapper.isNull(Blog::getDeleted);
        wrapper.eq(Blog::getTitle, title);

        return blogMapper.selectOne(wrapper);

    }
}

